# coding:utf8
# register.py
# 功能说明：用户运行程序后，自动检测认证状态，如果未经认证，就需要注册。注册过程是用户将程序运行后显示的机器码（卷序号）发回给管理员，管理员通过加密后生成加密文件或字符串给回用户。
# 每次登录，在有注册文件或者注册码的情况下，软件就会通过DES和base64解码，如果解码后和重新获取的机器码一致，则通过认证，进入主程序。

import base64
import os
import stat
import time
import traceback
import easygui as eg

import win32api
import win32con
from pyDes import *
from basic.logger import logger


class register:
    def __init__(self):
        self.Des_Key = "BHC#@*UM"  # Key
        self.Des_IV = "21324354"  # 自定IV向量
        self.title = 'clicker'
        # self.regist_dir = 'C:\\Windows\\Program Files'
        self.regist_file = 'C:\\Users\\Public\\register'

    # 获取C盘卷序列号
    # 使用C盘卷序列号的优点是长度短，方便操作，比如1513085707，但是对C盘进行格式化或重装电脑等操作会影响C盘卷序列号。
    # win32api.GetVolumeInformation(Volume Name, Volume Serial Number, Maximum Component Length of a file name, Sys Flags, File System Name)
    # return('', 1513085707, 255, 65470719, 'NTFS'),volume serial number is  1513085707.
    def getCVolumeSerialNumber(self):
        CVolumeSerialNumber = win32api.GetVolumeInformation("C:\\")[1]
        # print chardet.detect(str(CVolumeSerialNumber))
        # print CVolumeSerialNumber
        if CVolumeSerialNumber:
            return str(
                CVolumeSerialNumber)  # number is long type，has to be changed to str for comparing to content after.
        else:
            return 0

    # 使用DES加base64的形式加密
    # 考虑过使用M2Crypto和rsa，但是都因为在windows环境中糟糕的安装配置过程而放弃
    def DesEncrypt(self, str):
        k = des(self.Des_Key, CBC, self.Des_IV, pad=None, padmode=PAD_PKCS5)
        EncryptStr = k.encrypt(str)
        # EncryptStr = binascii.unhexlify(k.encrypt(str))
        return base64.b64encode(EncryptStr).decode('utf-8')  # 转base64编码返回

    # des解码
    def DesDecrypt(self, str):
        k = des(self.Des_Key, CBC, self.Des_IV, pad=None, padmode=PAD_PKCS5)
        DecryptStr = k.decrypt(str)
        return DecryptStr

    # 获取注册码，验证成功后生成注册文件
    def regist(self):
        eg.msgbox("请把屏幕上的软件注册码提供给QQ714417743，以完成注册" + self.getCVolumeSerialNumber(), self.title)
        key = eg.enterbox("请输入您获取到的机器验证码：" + self.getCVolumeSerialNumber(), self.title)
        # 由于输入类似“12”这种不符合base64规则的字符串会引起异常，所以需要增加输入判断
        # while key

        if key:
            try:
                content = self.getCVolumeSerialNumber()
                # print chardet.detect(content)
                # print type(content)
                # print content
                # type(key_decrypted) is str
                key_decrypted = self.DesDecrypt(base64.b64decode(key)).decode('utf-8')
                if content != 0 and key_decrypted != 0:
                    if content != key_decrypted:
                        eg.msgbox("您输入的注册码不成功，请联系QQ714417743")
                        self.regist()
                    elif content == key_decrypted:
                        # 读写文件要加判断
                        win32api.SetFileAttributes(self.regist_file, win32con.FILE_ATTRIBUTE_NORMAL)
                        with open(self.regist_file, 'a') as f:
                            f.write(key)
                            f.close()
                        win32api.SetFileAttributes(self.regist_file, win32con.FILE_ATTRIBUTE_HIDDEN)
                        eg.msgbox("clicker注册成功", self.title)
                        return True
                    else:
                        return False
                else:
                    return False
            except:
                logger.error(traceback.format_exc())
                self.regist()
                return False
        else:
            sys.exit(0)
        return False

    # 软件使用初始化
    def initialize(self):
        # 判断是否有regist文件，没有则创建
        with open(self.regist_file, 'w+') as f:
            start_time = last_time = str(time.time())
            f.write(self.DesEncrypt(start_time[0:10]))
            f.write(';')
            f.write(self.DesEncrypt(last_time[0:10]))
            f.write(';')
            f.close()
        win32api.SetFileAttributes(self.regist_file, win32con.FILE_ATTRIBUTE_HIDDEN)
        # 创建regist文件到本地，存储开始使用时间，最后使用时间

    # 注册校验
    def checkAuthored(self):
        content = self.getCVolumeSerialNumber()
        checkAuthoredResult = 0
        # 读写文件要加判断
        try:
            f = open(self.regist_file, 'r')
            if f:
                key = f.read()
                if key:
                    list = key.split(";")
                    start_time = int(self.DesDecrypt(base64.b64decode(list[0])))
                    last_time = int(self.DesDecrypt(base64.b64decode(list[1])))
                    now_time = int(time.time())
                    mechanic_code = self.DesDecrypt(base64.b64decode(list[2]))
                    if mechanic_code:
                        if mechanic_code.decode('utf-8') == content:
                            logger.info("clicker认证通过")
                            checkAuthoredResult = 1
                        else:
                            logger.info("clicker认证失败，请联系QQ:714417743获取认证")
                            checkAuthoredResult = -1
                    elif now_time < last_time or now_time - start_time < 15*24*60*60:
                        # 使用试用期
                        choice = eg.buttonbox("试用期认证通过，试用期还剩：" + str(int((15*24*60*60-now_time + start_time)/60/60)) + '小时', title=self.title, choices=("注册", "试用", "退出"))
                        if choice == '注册':
                            self.regist()
                            checkAuthoredResult = 1
                        elif choice == '试用':
                            checkAuthoredResult = 2
                        else:
                            sys.exit(0)
                    else:
                        logger.info("clicker机器码认证未通过")
                        checkAuthoredResult = -2
                else:
                    checkAuthoredResult = -3
        except IOError:
            # 完成初始化后，提醒用户注册或试用
            self.initialize()
            choice = eg.buttonbox("欢迎使用clicker", title= self.title, choices=("注册", "试用", "退出"))
            if choice == '注册':
                eg.msgbox("请把屏幕上的软件注册码:" + self.getCVolumeSerialNumber() + ",提供给QQ714417743，以完成注册", self.title)
                self.regist()
                checkAuthoredResult = self.checkAuthored()
            elif choice == '试用':
                checkAuthoredResult = self.checkAuthored()
            else:
                sys.exit(0)
        return checkAuthoredResult

if __name__ == '__main__':
    reg = register()
    # 1382165971
    # print(reg.DesEncrypt('1382165971'))
    # print(reg.DesDecrypt(base64.b64decode('W9n155w/apGRB7F5zsRhAQ==')))
    #
    # print(reg.DesEncrypt(str(int(time.time()))))
    # print(reg.DesDecrypt(base64.b64encode('uYh81Gi6tmnmh1Nxy12drk9DBcjrIESd')))
    # reg.regist()
    eg.msgbox(msg="我一定要学会编程！",title="标题部分",ok_button="加油")
    # reg.checkAuthored()

    # os.chmod(reg.regist_dir, stat.S_IWGRP)

    # os.
    with open(reg.regist_file, 'w') as f:
        f.write("鞋垫东西")
        f.close()

    with open(reg.regist_file, 'r') as f:
        print(f.read())
        f.close()